package com.rgs.se.concurrent.lock;


import redis.clients.jedis.Jedis;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * @author Ren Gaoshuai
 * @ClassName LocksRedis
 * @Description redis实现分布式id
 * @date 2021-10-27 11:19
 **/
public class LocksRedis {

    private final static String IP = "127.0.0.1";
    private final static int PORT = 6379;

    private static Jedis jedis;
    private static int num = 0;
    private static String lock = "lock";
    private static String lockValue = "lockValue";

    static ExecutorService executorService = Executors.newFixedThreadPool(2);

    public static void main(String[] args) {

        Jedis jedis =  new Jedis(IP ,PORT,3000);
        JedisLock jedisLock = new JedisLock(jedis);

        executorService.execute(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    if (jedisLock.lock(10000,1)){
                        num++;
                        System.out.println(Thread.currentThread().getName() + " "  + getStringDateFormat() + " "+ num);

                    }
                    jedisLock.unLock();
                }
            }
        });

        executorService.execute(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    if (jedisLock.lock(10000,1)){
                        num++;
                        System.out.println(Thread.currentThread().getName() + " "  + getStringDateFormat() + " "+ num);

                    }
                    jedisLock.unLock();
                }
            }
        });

        try {
            executorService.shutdown();
            executorService.awaitTermination(100, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }



    static class JedisLock{
        Jedis jedis;
        public JedisLock(Jedis jedis){
            this.jedis = jedis;
            jedis.del(lock);
        }

        /**
         * 上锁
         * @param timeout 超时时间
         * @param expire 过期时间
         * @return
         */
        public boolean lock(long timeout,int expire){
            long nanoTime = System.nanoTime();
            try {
                while(true){
                    //当key不存在是，设置值，成功返回1 失败返回0
                    if (jedis.setnx(lock,lockValue) == 1L){
                        //设置超时时间
                        jedis.expire(lock,expire);
                        break;
                    }else{
                        //等待
                        System.out.println("出现等待");
                        Thread.sleep(10);
                    }
                }
            } catch (Exception e) {
                jedis = new Jedis(IP,PORT,3000);
                e.printStackTrace();
            }
            return true;
        }

        /**
         * 释放锁
         */
        public void unLock(){
            try {
                jedis.del(lock);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    /**
     * 获取当前时间字符串
     * 高并发情况下不能保证唯一，后面需要拼接编号
     * @return
     */
    public static String getStringDateFormat(){
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        return dtf.format(now);
    }
}
